home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
Libraries
/
Dots & Pixels
/
sources
/
gworld.cp
< prev
next >
Wrap
Text File
|
1995-09-29
|
8KB
|
236 lines
#include <stdlib.h>
#include <Windows.h>
#include <QDOffscreen.h>
#include <Memory.h>
#include <Fonts.h>
#include <Packages.h>
#include <SegLoad.h>
#include <ToolUtils.h>
#include <TextEdit.h>
#include <Files.h>
#include "C_randomizer.h"
#include "general.h"
#include "port.h"
#include "gworld.h"
const unsigned short gworld::extensions[ 256] =
{
0x0000, 0x0003, 0x000C, 0x000F, 0x0030, 0x0033, 0x003C, 0x003F,
0x00C0, 0x00C3, 0x00CC, 0x00CF, 0x00F0, 0x00F3, 0x00FC, 0x00FF,
0x0300, 0x0303, 0x030C, 0x030F, 0x0330, 0x0333, 0x033C, 0x033F,
0x03C0, 0x03C3, 0x03CC, 0x03CF, 0x03F0, 0x03F3, 0x03FC, 0x03FF,
0x0C00, 0x0C03, 0x0C0C, 0x0C0F, 0x0C30, 0x0C33, 0x0C3C, 0x0C3F,
0x0CC0, 0x0CC3, 0x0CCC, 0x0CCF, 0x0CF0, 0x0CF3, 0x0CFC, 0x0CFF,
0x0F00, 0x0F03, 0x0F0C, 0x0F0F, 0x0F30, 0x0F33, 0x0F3C, 0x0F3F,
0x0FC0, 0x0FC3, 0x0FCC, 0x0FCF, 0x0FF0, 0x0FF3, 0x0FFC, 0x0FFF,
0x3000, 0x3003, 0x300C, 0x300F, 0x3030, 0x3033, 0x303C, 0x303F,
0x30C0, 0x30C3, 0x30CC, 0x30CF, 0x30F0, 0x30F3, 0x30FC, 0x30FF,
0x3300, 0x3303, 0x330C, 0x330F, 0x3330, 0x3333, 0x333C, 0x333F,
0x33C0, 0x33C3, 0x33CC, 0x33CF, 0x33F0, 0x33F3, 0x33FC, 0x33FF,
0x3C00, 0x3C03, 0x3C0C, 0x3C0F, 0x3C30, 0x3C33, 0x3C3C, 0x3C3F,
0x3CC0, 0x3CC3, 0x3CCC, 0x3CCF, 0x3CF0, 0x3CF3, 0x3CFC, 0x3CFF,
0x3F00, 0x3F03, 0x3F0C, 0x3F0F, 0x3F30, 0x3F33, 0x3F3C, 0x3F3F,
0x3FC0, 0x3FC3, 0x3FCC, 0x3FCF, 0x3FF0, 0x3FF3, 0x3FFC, 0x3FFF,
0xC000, 0xC003, 0xC00C, 0xC00F, 0xC030, 0xC033, 0xC03C, 0xC03F,
0xC0C0, 0xC0C3, 0xC0CC, 0xC0CF, 0xC0F0, 0xC0F3, 0xC0FC, 0xC0FF,
0xC300, 0xC303, 0xC30C, 0xC30F, 0xC330, 0xC333, 0xC33C, 0xC33F,
0xC3C0, 0xC3C3, 0xC3CC, 0xC3CF, 0xC3F0, 0xC3F3, 0xC3FC, 0xC3FF,
0xCC00, 0xCC03, 0xCC0C, 0xCC0F, 0xCC30, 0xCC33, 0xCC3C, 0xCC3F,
0xCCC0, 0xCCC3, 0xCCCC, 0xCCCF, 0xCCF0, 0xCCF3, 0xCCFC, 0xCCFF,
0xCF00, 0xCF03, 0xCF0C, 0xCF0F, 0xCF30, 0xCF33, 0xCF3C, 0xCF3F,
0xCFC0, 0xCFC3, 0xCFCC, 0xCFCF, 0xCFF0, 0xCFF3, 0xCFFC, 0xCFFF,
0xF000, 0xF003, 0xF00C, 0xF00F, 0xF030, 0xF033, 0xF03C, 0xF03F,
0xF0C0, 0xF0C3, 0xF0CC, 0xF0CF, 0xF0F0, 0xF0F3, 0xF0FC, 0xF0FF,
0xF300, 0xF303, 0xF30C, 0xF30F, 0xF330, 0xF333, 0xF33C, 0xF33F,
0xF3C0, 0xF3C3, 0xF3CC, 0xF3CF, 0xF3F0, 0xF3F3, 0xF3FC, 0xF3FF,
0xFC00, 0xFC03, 0xFC0C, 0xFC0F, 0xFC30, 0xFC33, 0xFC3C, 0xFC3F,
0xFCC0, 0xFCC3, 0xFCCC, 0xFCCF, 0xFCF0, 0xFCF3, 0xFCFC, 0xFCFF,
0xFF00, 0xFF03, 0xFF0C, 0xFF0F, 0xFF30, 0xFF33, 0xFF3C, 0xFF3F,
0xFFC0, 0xFFC3, 0xFFCC, 0xFFCF, 0xFFF0, 0xFFF3, 0xFFFC, 0xFFFF
};
gworld::gworld( int breedte, int hoogte, int diepte, port &original)
{
if( (diepte != 1) && (diepte != 2) && (diepte != 4)
&& (diepte != 8) && (diepte != 16) && (diepte != 32))
{
DebugStr( "\pgworld::gworld: illegal depth passed");
exit( EXIT_FAILURE);
}
if( (hoogte <= 0) || (breedte <= 0))
{
DebugStr( "\pgworld::gworld: illegal width and/or height passed");
exit( EXIT_FAILURE);
}
myRect.top = 0;
myRect.left = 0;
myRect.bottom = hoogte;
myRect.right = breedte;
de_diepte = diepte;
if( NewGWorld( &myGWorldPtr, de_diepte, &myRect, nil, original.getGDevice(), noNewDevice) != noErr)
{
//
// retry in temporary memory. We do not set the 'AllowPurgePixels' bit.
// This is not the proper thing to do, but doing it this way is better than
// failing immediately.
//
CheckForError( NewGWorld(
&myGWorldPtr, de_diepte, &myRect, nil, original.getGDevice(), noNewDevice | useTempMem), "NewGWorld");
}
myGDHandle = GetGWorldDevice( myGWorldPtr);
const PixMapHandle myPixMapH = GetGWorldPixMap( myGWorldPtr);
CheckForError( !LockPixels( myPixMapH), "LockPixels");
HLock( (Handle)myPixMapH);
myPix = (*myPixMapH);
}
gworld::gworld( int breedte, int hoogte, int diepte, CTabHandle cTable)
{
if( (diepte != 1) && (diepte != 2) && (diepte != 4)
&& (diepte != 8) && (diepte != 16) && (diepte != 32))
{
DebugStr( "\pgworld::gworld: illegal depth passed");
exit( EXIT_FAILURE);
}
if( (hoogte <= 0) || (breedte <= 0))
{
DebugStr( "\pgworld::gworld: illegal width and/or height passed");
exit( EXIT_FAILURE);
}
myRect.top = 0;
myRect.left = 0;
myRect.bottom = hoogte;
myRect.right = breedte;
de_diepte = diepte;
if( NewGWorld( &myGWorldPtr, de_diepte, &myRect, cTable, nil, 0) != noErr)
{
//
// retry in temporary memory. We do not set the 'AllowPurgePixels' bit.
// This is not the proper thing to do, but doing it this way is better than
// failing immediately.
//
CheckForError( NewGWorld(
&myGWorldPtr, de_diepte, &myRect, cTable, nil, useTempMem), "NewGWorld");
}
myGDHandle = GetGWorldDevice( myGWorldPtr);
const PixMapHandle myPixMapH = GetGWorldPixMap( myGWorldPtr);
CheckForError( !LockPixels( myPixMapH), "LockPixels");
HLock( (Handle)myPixMapH);
myPix = (*myPixMapH);
}
gworld::~gworld()
{
const PixMapHandle myPixMapH = GetGWorldPixMap( myGWorldPtr);
HUnlock( (Handle)myPixMapH);
UnlockPixels( myPixMapH);
DisposeGWorld( myGWorldPtr);
}
void gworld::fill_random() const
{
//
// Note: this could be done faster since randomizer_step() returns an
// unsigned long. However, this would take some extra code since we can
// not be sure that rowBytes is a multiple of four.
// Random probably is even slower, but we could do a GetTrapAdress to
// prevent trap overhead.
// 941101: Now doing it the faster way. This could have been done all
// along. Since a pixmap is contiguous in memory we only have to take a
// pad word into account at the end of the pixmap data.
// => only one loop needed.
//
const int rowChars = myPix->rowBytes & 0x2FFF;
const int numRows = myPix->bounds.bottom - myPix->bounds.top;
const int totalChars = rowChars * numRows; // always even, rowChars is even
const int totalLongs = totalChars / 4;
const int pad_them = (totalChars & 2) != 0;
unsigned long *curAddress = (unsigned long *)myPix->baseAddr; // pray it to be even ;->
randomizer_fill( curAddress, totalLongs);
if( pad_them)
{
unsigned short *curAddresToo = (unsigned short *)(curAddress + totalLongs);
*curAddresToo = randomizer_step();
}
}
void gworld::two_bit_merge( const gworld &left, const gworld &right) const
{
if( (de_diepte != 2) || (left.de_diepte != 1) || (right.de_diepte != 1))
{
DebugStr( "\pgworld::two_bit_merge: depths not 2, 1, and 1");
exit( EXIT_FAILURE);
}
const int left_rowBytes = left.myPix->rowBytes & 0x2FFF;
const int right_rowBytes = right.myPix->rowBytes & 0x2FFF;
const int rowWords = (myPix->rowBytes & 0x2FFF) / 2; // always even => division is safe
//
// Note: contrary to what one would expect one does not have to have
// 'rowWords == left_rowBytes' when both worlds are of equal width,
// and have depths 1 and 2. Two GWorlds of (equal) depth one do have
// equal values of rowBytes, though.
//
if( (left_rowBytes != right_rowBytes) || (rowWords > left_rowBytes))
{
DebugStr( "\pgworld::two_bit_merge: rowBytes and/or rowWords don't match");
exit( EXIT_FAILURE);
}
const int numRows = myPix->bounds.bottom - myPix->bounds.top;
unsigned short *curAddress = (unsigned short *)myPix->baseAddr;
unsigned char *leftAddress = (unsigned char *)left.myPix->baseAddr;
unsigned char *rightAddress = (unsigned char *)right.myPix->baseAddr;
for( int row = 0; row < numRows; row++)
{
unsigned char *leftRow = leftAddress;
unsigned char *rightRow = rightAddress;
for( int wordNo = 0; wordNo < rowWords; wordNo++)
{
const unsigned short left_extended = extendChar( *leftRow++);
const unsigned short right_extended = extendChar( *rightRow++);
*curAddress++ = (left_extended & 0xAAAA) | (right_extended & 0x5555);
}
leftAddress += left_rowBytes;
rightAddress += right_rowBytes;
}
}
OSErr gworld::dump( short defile) const
{
const int rowChars = (myPix->rowBytes & 0x2FFF);
const int numRows = myPix->bounds.bottom - myPix->bounds.top;
long totalChars = rowChars * numRows;
const void *curAddress = (const void *)myPix->baseAddr;
return FSWrite( defile, &totalChars, curAddress);
}
OSErr gworld::load( short defile) const
{
const int rowChars = (myPix->rowBytes & 0x2FFF);
const int numRows = myPix->bounds.bottom - myPix->bounds.top;
long totalChars = rowChars * numRows;
void *curAddress = (void *)myPix->baseAddr;
return FSRead( defile, &totalChars, curAddress);
}